package io

import (
	"context"
	"net/http"

	"github.com/gorilla-go/container"
	"github.com/gorilla-go/pig/constant"
	"github.com/gorilla-go/pig/middleware/io/params"
)

type Input struct {
	Request            *http.Request
	paramVarCollection *params.ParamVarCollection
	postVarCollection  *params.PostVarCollection
}

// IsAjax 判断是否是 AJAX 请求
func (i *Input) IsAjax() bool {
	return i.Request.Header.Get("X-Requested-With") == "XMLHttpRequest"
}

// IsPost 判断是否是 POST 请求
func (i *Input) IsPost() bool {
	return i.Request.Method == http.MethodPost
}

// IsGet 判断是否是 GET 请求
func (i *Input) IsGet() bool {
	return i.Request.Method == http.MethodGet
}

// IsPut 判断是否是 PUT 请求
func (i *Input) IsPut() bool {
	return i.Request.Method == http.MethodPut
}

// IsDelete 判断是否是 DELETE 请求
func (i *Input) IsDelete() bool {
	return i.Request.Method == http.MethodDelete
}

// ParamVars 获取参数
func (i *Input) ParamVars() *params.ParamVarCollection {
	return i.paramVarCollection
}

// PostVars 获取 POST 参数
func (i *Input) PostVars() *params.PostVarCollection {
	return i.postVarCollection
}

// GetInput 获取 Input 对象
func GetInput(ctx context.Context) *Input {
	c := ctx.Value(constant.Container).(*container.Container)
	return container.GetMustLazySingletonByAlias[*Input](c, constant.Input)
}

// InputFormatter 输入格式化器
var InputFormatter = func(ctx context.Context, next func(ctx context.Context)) {
	c := ctx.Value(constant.Container).(*container.Container)
	container.SetLazySingletonWithAlias(c, string(constant.Input), func() *Input {
		request := container.GetMustSingletonByAlias[*http.Request](c, constant.Request)

		// 设置 query 请求参数
		queryParams := request.URL.Query()
		routerParams := ctx.Value(constant.RouterParams).(map[string]string)
		for key, value := range routerParams {
			queryParams.Add(key, value)
		}

		// 解析 form-data 和 x-www-form-urlencoded 格式的数据
		err := request.ParseMultipartForm(32 << 20) // 32MB 最大内存
		if err != nil {
			// 如果不是 multipart 格式，尝试解析普通表单
			err = request.ParseForm()
			if err != nil {
				panic(err)
			}
		}

		// 返回 Input 对象
		return &Input{
			Request: request,
			paramVarCollection: &params.ParamVarCollection{
				Params: queryParams,
			},
			postVarCollection: &params.PostVarCollection{
				Params: request.PostForm,
				Files:  request.MultipartForm.File,
			},
		}
	})
	next(ctx)
}
